﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="HolidaysSliderPanel.cs" company="BerlinSoft">
//   Wernfried Schwenkner
// </copyright>
// <summary>
//   Defines the HolidaysSliderPanel type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Data.SqlServerCe;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using SenseTimeTracker.Main;
using SenseTimeTracker.Misc;
using SenseTimeTracker.Properties;
using StedySoft.SenseSDK;
using StedySoft.SenseSDK.DrawingCE;

namespace SenseTimeTracker.Holidays
{
	public class HolidaysSliderPanel : CommonSliderPanel<Calendar.Holiday>
	{
		private MenuItem menuItemResetHolidays;

		public HolidaysSliderPanel(SenseTimeTrackerForm form)
			: base(form, "HolidaySmallIcon.png", "HolidayLargeIcon.png", MenuEnty.New | MenuEnty.Edit | MenuEnty.Remove)
		{
			sorting = Persistance.Instance.HolidaysSorting;
			sortColumns = SortColumn.Name | SortColumn.Date;

			menuItemResetHolidays = new MenuItem();
			menuItemResetHolidays.Text = Resources.MenuItemReset;
			menuItemResetHolidays.Click += MenuItemNewEntry_Click;
			menuItem.MenuItems.Add(menuItemResetHolidays);
			foreach (FieldInfo fieldInfo in typeof(Calendar.Holiday.Regions).GetFields(BindingFlags.Static | BindingFlags.Public))
			{
				if ((int)fieldInfo.GetValue(null) != 0xffff)
				{
					MenuItem monthMenuItem = new MenuItem();
					monthMenuItem.Text = fieldInfo.Name;
					monthMenuItem.Click += menuItem_Click;
					menuItemResetHolidays.MenuItems.Add(monthMenuItem);
				}
			}
		}

		public override string Name { get { return Resources.PanelHolidayName; } }

		protected override void MenuItemNewEntry_Click(object sender, EventArgs e)
		{
			using (new DialogHelper(ownedForm))
			{
				HolidaysEditForm form = new HolidaysEditForm
				{
					Holiday = new Calendar.Holiday(),
				};
				if (form.ShowDialog() == DialogResult.OK)
				{
					SqlCeCommand command = new SqlCeCommand(
						"INSERT INTO Holidays " +
						"(holidayId, personId, name, type, day, month, dayofweek, count, utilisation, enabled, fixed) " +
						"VALUES (@holidayId, @personId, @name, @type, @day, @month, @dayofweek, @count, @utilisation, @enabled, @fixed)",
						DatabaseManager.DbConnection);
					command.Parameters.Add("@holidayId", Guid.NewGuid());
					command.Parameters.Add("@personId", Persistance.Instance.UserId);
					command.Parameters.Add("@name", form.Holiday.Name);
					command.Parameters.Add("@type", form.Holiday.Type);
					command.Parameters.Add("@day", form.Holiday.Day);
					command.Parameters.Add("@month", form.Holiday.Month);
					command.Parameters.Add("@dayofweek", form.Holiday.DayOfWeek);
					command.Parameters.Add("@count", form.Holiday.Count);
					command.Parameters.Add("@utilisation", form.Holiday.Utilisation);
					command.Parameters.Add("@enabled", true);
					command.Parameters.Add("@fixed", false);
					DatabaseManager.DbConnection.Open();
					command.ExecuteNonQuery();
					DatabaseManager.DbConnection.Close();
					Bind(senseListControl);
				}
			}
		}

		/// <summary>
		/// Handles edit menu item click event
		/// </summary>
		/// <param name="sender">The sender of the event.</param>
		/// <param name="e">The event arguments.</param>
		protected override void MenuItemEditEntry_Click(object sender, EventArgs e)
		{
			SqlCeCommand command = new SqlCeCommand(
				"SELECT name, type, day, month, dayofweek, count, utilisation, fixed " +
				"FROM Holidays " +
				"WHERE holidayId = @holidayId",
				DatabaseManager.DbConnection);
			command.Parameters.Add("@holidayId", senseListControl.FocusedItem.Tag);
			DatabaseManager.DbConnection.Open();
			SqlCeDataReader reader = command.ExecuteReader();
			if (reader.Read())
			{
				bool edit = true;
				if ((bool)reader["fixed"])
				{
					edit = SenseAPIs.SenseMessageBox.Show(Resources.DialogModifySystemHolidayQuestion, Resources.DialogHeaderEditHoliday, SenseMessageBoxButtons.YesNo) == DialogResult.Yes;
				}

				if (edit)
				{
					using (new DialogHelper(ownedForm))
					{
						HolidaysEditForm form = new HolidaysEditForm
						{
							Holiday = new Calendar.Holiday
							{
								Name = reader["name"].ToString(),
								Type = (Calendar.Holiday.HolidayType)reader["type"],
								Day = (int)reader["day"],
								Month = (int)reader["month"],
								DayOfWeek = (DayOfWeek)reader["dayofweek"],
								Count = (int)reader["count"],
								Utilisation = (int)reader["utilisation"],
							}
						};
						if (form.ShowDialog() == DialogResult.OK)
						{
							command.CommandText =
								"UPDATE Holidays SET " +
								"name = @name, " +
								"type = @type, " +
								"day = @day, " +
								"month = @month, " +
								"dayofweek = @dayofweek, " +
								"count = @count, " +
								"utilisation = @utilisation " +
								"WHERE holidayId = @holidayId";
							command.Parameters.Add("@name", form.Holiday.Name);
							command.Parameters.Add("@type", form.Holiday.Type);
							command.Parameters.Add("@day", form.Holiday.Day);
							command.Parameters.Add("@month", form.Holiday.Month);
							command.Parameters.Add("@dayofweek", form.Holiday.DayOfWeek);
							command.Parameters.Add("@count", form.Holiday.Count);
							command.Parameters.Add("@utilisation", form.Holiday.Utilisation);
							command.ExecuteNonQuery();
						}
					}
				}
			}

			DatabaseManager.DbConnection.Close();
			Bind(senseListControl);
		}

		protected override void MenuItemRemoveEntry_Click(object sender, EventArgs e)
		{
			if (SenseAPIs.SenseMessageBox.Show(Resources.DialogDeleteQuestion, Resources.DialogHeaderRemoveHoliday, SenseMessageBoxButtons.YesNo) == DialogResult.Yes)
			{
				SqlCeCommand command = new SqlCeCommand("SELECT fixed FROM Holidays WHERE holidayId = @holidayId", DatabaseManager.DbConnection);
				command.Parameters.Add("@holidayId", senseListControl.FocusedItem.Tag);
				DatabaseManager.DbConnection.Open();
				bool remove = true;
				if ((bool)command.ExecuteScalar())
				{
					remove = SenseAPIs.SenseMessageBox.Show(Resources.DialogRemoveSystemHolidayQuestion, Resources.DialogHeaderRemoveHoliday, SenseMessageBoxButtons.YesNo) == DialogResult.Yes;
				}
				DatabaseManager.DbConnection.Close();

				if (remove)
				{
					command.CommandText = "DELETE FROM Holidays WHERE holidayId = @holidayId";
					DatabaseManager.DbConnection.Open();
					command.ExecuteNonQuery();
					DatabaseManager.DbConnection.Close();
					Bind(senseListControl);
				}
			}
		}

		public override void Bind(SenseListControl senseListControl)
		{
			base.Bind(senseListControl);

			SqlCeCommand command = new SqlCeCommand(
				"SELECT holidayId, enabled, name, type, day, month, dayofweek, count, fixed " +
				"FROM Holidays WHERE personId=@personId",
				DatabaseManager.DbConnection);
			command.Parameters.Add("personId", Persistance.Instance.UserId);
			DatabaseManager.DbConnection.Open();
			SqlCeDataReader reader = command.ExecuteReader();
			List<Calendar.Holiday> holidays = new List<Calendar.Holiday>();
			while (reader.Read())
			{
				holidays.Add(new Calendar.Holiday
				{
					Day = (int)reader["day"],
					Month = (int)reader["month"],
					DayOfWeek = (DayOfWeek)reader["dayofweek"],
					Count = (int)reader["count"],
					Type = (Calendar.Holiday.HolidayType)reader["type"],
					Name = Resources.ResourceManager.GetString(reader["name"].ToString(), Resources.Culture),
					Enabled = (bool)reader["enabled"],
					Fixed = (bool)reader["fixed"],
					Id = (Guid)reader["holidayId"],
				});
			}

			var filteredHolidays = from holiday in holidays select holiday;
			SortFilter(ref filteredHolidays);
			foreach (Calendar.Holiday holiday in filteredHolidays)
			{
				SensePanelCheckboxItem item = new SensePanelCheckboxItem();
				item.PrimaryText = holiday.Name;
				item.SecondaryText = holiday.Date(0).ToShortDateString();
				item.Status = holiday.Enabled ? ItemStatus.On : ItemStatus.Off;
				item.OnStatusChanged += item_OnStatusChanged;
				item.Tag = holiday.Id;
				item.Name = Guid.NewGuid().ToString();
				senseListControl.AddItem(item);
			}

			DatabaseManager.DbConnection.Close();
		}

		public override void BindFilter()
		{
			BindFilter(Resources.HolidaysFilterHeader);
		}

		void item_OnStatusChanged(object Sender, ItemStatus Status)
		{
			SqlCeCommand command = new SqlCeCommand(
				"UPDATE Holidays SET enabled = @enabled WHERE holidayId = @holidayId",
				DatabaseManager.DbConnection);
			command.Parameters.Add("@enabled", Status == ItemStatus.On);
			command.Parameters.Add("@holidayId", ((SensePanelCheckboxItem)Sender).Tag);
			DatabaseManager.DbConnection.Open();
			command.ExecuteNonQuery();
			DatabaseManager.DbConnection.Close();
		}

		/// <summary>
		/// Reset holiday list to predefined holidays for a given region
		/// </summary>
		/// <param name="region">
		/// The region.
		/// </param>
		private void ResetHolidays(Calendar.Holiday.Regions region)
		{
			SqlCeCommand command = new SqlCeCommand(
				"DELETE FROM Holidays " +
				"WHERE personId = @personId AND fixed = @fixed",
				DatabaseManager.DbConnection);
			command.Parameters.Add("@personId", Persistance.Instance.UserId);
			command.Parameters.Add("@fixed", true);
			DatabaseManager.DbConnection.Open();
			command.ExecuteNonQuery();
			command.CommandText =
				"INSERT INTO Holidays " +
				"(holidayId, personId, name, type, day, month, dayofweek, count, utilisation, enabled, fixed) " +
				"VALUES (@holidayId, @personId, @name, @type, @day, @month, @dayofweek, @count, @utilisation, @enabled, @fixed)";
			command.Parameters.Add("@holidayId", null);
			command.Parameters.Add("@name", null);
			command.Parameters.Add("@type", null);
			command.Parameters.Add("@day", null);
			command.Parameters.Add("@month", null);
			command.Parameters.Add("@dayofweek", null);
			command.Parameters.Add("@count", null);
			command.Parameters.Add("@utilisation", null);
			command.Parameters.Add("@enabled", true);
			command.Parameters.Add("@fixed", true);
			foreach (Calendar.Holiday holiday in Calendar.DefaultHolidays)
			{
				if ((holiday.Region & (int)region) != 0)
				{
					command.Parameters["@holidayId"].Value = Guid.NewGuid();
					command.Parameters["@name"].Value = holiday.Name;
					command.Parameters["@type"].Value = holiday.Type;
					command.Parameters["@day"].Value = holiday.Day;
					command.Parameters["@month"].Value = holiday.Month;
					command.Parameters["@dayofweek"].Value = holiday.DayOfWeek;
					command.Parameters["@count"].Value = holiday.Count;
					command.Parameters["@utilisation"].Value = holiday.Utilisation;
					command.ExecuteNonQuery();
				}
			}

			DatabaseManager.DbConnection.Close();
			Bind(senseListControl);
		}

		void menuItem_Click(object sender, EventArgs e)
		{
			ResetHolidays((Calendar.Holiday.Regions)Enum.Parse(typeof(Calendar.Holiday.Regions), ((MenuItem)sender).Text, true));
		}
	}
}
